home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
PROGRAMM
/
PASCAL
/
0191.ZIP
/
FINDUP32.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1986-01-15
|
61KB
|
1,343 lines
program FindDuplicateFiles;
{ ╔══════════════════════════════════════════════════════════════════════╗
║ Copyright March 25, 1985 ║
║ ║
║ It must not be sold to anyone for any purpose it has been placed ║
║ in the public domain for the use of computer hackers who love to ║
║ play with their machines. ║
╠══════════════════════════════════════════════════════════════════════╣
║ Version 1.0 by Karson Morrison ║
║ ║
║ Anyone who modifies this program place your name and the new ║
║ version number by it. Place a comment before and after your ║
║ changes and place the version number as part of those ║
║ comments. ║
║ ║
║ Please send me a copy of the changes that you have made so ║
║ that I may include them in the master. I don't have all the ║
║ answers I just started it. I am not very knowledgeable at ║
║ Pascal and I may have made some routines that could be made ║
║ more efficient by using other coding. If you find those ║
║ please let me know and I will include them to make the ║
║ program faster. I cannot make the sort any faster because ║
║ it was coded by Borland. Anyone who sends me changes I ║
║ will include on a list that I will notify of all changes ║
║ that are made to the program. Keep those cards and letters ║
║ flowing. ║
╠══════════════════════════════════════════════════════════════════════╣
║ This is a program to list out all of the files on a disk sorted ║
║ in file order. It will also tell you of any duplicate files ║
║ within different directories. (See Version 2.0 changes) ║
╠══════════════════════════════════════════════════════════════════════╣
║ Requirements: ║
║ ║
║ This program requires Turbo Pascal 2.0 and the Turbo Toolbox ║
║ pascal program SORT.BOX. The .COM version has already been ║
║ compiled with the SORT in it. ║
╠══════════════════════════════════════════════════════════════════════╣
║ This program was written by and Copyright (C) 1985 by ║
║ ║
║ Karson W. Morrison ║
║ RD. 1, Box 531, ║
║ Ringoes, NJ. 08551 ║
║ (201) 788-1846 ║
╠══════════════════════════════════════════════════════════════════════╣
║ Acknowledgements: ║
║ ║
║ I used info picked up from a bulletin board for the routines ║
║ to get system date and time. That info. was created by Jon Gray ║
║ of the IBM PC USERS GROUP Milwaukee. It did have a bug though ║
║ that would only work with months of 2 digits (now fixed by me). ║
║ ║
║ I also used routines provided by Borland for the reading of ║
║ directories. This info was provided in their Turbo Tutor package. ║
║ ║
║ Tears: ║
║ ║
║ A lot of hours went into this program please do not revise it and ║
║ leave out the credit that I have done most of the work. ║
║ ║
║ Purpose: ║
║ ║
║ Every time I turned around I was trying to delete some of the ║
║ files on my hard disk because I was always ending up with only ║
║ 300 - 400 K left. I kept thinking there must be an easier way ║
║ to know if there were duplicate files. ║
║ ║
║ This is the result ║
╠══════════════════════════════════════════════════════════════════════╣
║ Version 2.0 March 25, 1985 ║
║ Made by the author. ║
║ ║
║ Updated program to put file size on each line and put in a major ║
║ option for Sorted Tree Directories. ║
║ ║
║ Every Tree Dir program that I have seen always intersperces sub ║
║ directories files where it finds them with the regular files in ║
║ that directory. This program put files together, followed by ║
║ the sub directory files in that directory. The sub directories ║
║ are sorted, and then printed in the sorted order within the ║
║ the parent directory. ║
║ ║
║ Updated program to put output on a file DIRECTRY.DTA as an option ║
║ for later printing or other modification. ║
╠══════════════════════════════════════════════════════════════════════╣
║ Version 2.01 April 23, 1985 ║
║ Made by the author. ║
║ ║
║ Made a change to increase the valid characters that may be in a ║
║ file name. The 7Fh, DEL char may be in a file name there by ║
║ making the file name unable to be entered from the keyboard. ║
║ ║
║ This also is used to make a directory hidden. ║
║ Fix the line which prints on the screen when a report is being ║
║ produced on paper. ║
╠══════════════════════════════════════════════════════════════════════╣
║ Version 2.02 July 28, 1985 ║
║ Made by the author. ║
║ ║
║ Made a change to put a Clrscr in at the beginning of the program. ║
║ This was necessary if you use the Public Domain program to reset ║
║ the clear screen at the begining of the program. ║
║ Turbo 3.0 also doesn't clear screen at beginning of program. ║
╠══════════════════════════════════════════════════════════════════════╣
║ Version 2.03 September 9, 1985 ║
║ Made by the author. ║
║ ║
║ Made a change to calculate to space used for 1K blocks which is ║
║ what is used when the data is stored on a floppy. ║
╠══════════════════════════════════════════════════════════════════════╣
║ Version 2.04 November 11, 1985 ║
║ Made by author ║
║ ║
║ Made a change to the first screen so that it would be easier to ║
║ understand the options. Included Windows by Lynn Canning, ║
║ with the original code by Lane Farris. ║
╠══════════════════════════════════════════════════════════════════════╣
║ Version 3.00 December 14, 1985 ║
║ Made by author ║
║ This version now requires Turbo 3.0 ║
║ ║
║ This version now will read multiple hard disks and floppies and ║
║ do its thing on the file names. ║
║ ║
║ Option 1, 2, 4 will allow you to go to the screen, printer ║
║ or disk file. ║
║ Option 3 will only go to disk file 'DIRECTRY.DTA' for the ║
║ directory and 'DUPLICAT.DTA' for the duplicate ║
║ entries. ║
║ ║
║ Option 4 Sorted Tree Directory uses the Drive letter as its ║
║ major sort key. Therefore it will not mix up file ║
║ and directories names from multiple drives. ║
║ ║
║ This version of the program also supports floppies. The program ║
║ would read them before but the output was not too useful because ║
║ only one floppy could be read at a time. *** NOW *** the program ║
║ asks you if you are reading a hard drive or a floppy. Nothing ║
║ happens to the machine if you answer the wrong answer, it is to ║
║ allow me to know if I should VolumeID the disk (I don't on Hard ║
║ Disks). If you want me to Volume-ID a floppy just enter the data ║
║ (What you enter will also show on the report as the main directory ║
║ If you don't enter a Volume-ID (return) I show the name 'FLOPPYnnn' ║
║ as the main directory. (nnn is the number of the diskette entered) ║
║ ║
║ If you want to speed up the entry process, and you have two or more ║
║ floppy drives run the program as FINDDUPE AB. The program will ║
║ alternate between the drives. (NOTE:) one problem in using this ║
║ feature you must have a floppy for both A and B drives. (You could ║
║ place a blank formatted floppy in the last B: drive to insure ║
║ the completion of the input phase.) ║
║ ║
║ Included into version 3.00 are changes made by Ray Bobak as he ║
║ noted below. ║
║ ║
║ Version 2.1 October 27, 1985 ║
║ Modifications by Ray Bobak ║
║ Sysop PC-RAIN Node II ║
║ Wappingers Falls, NY ║
║ 914-462-7674 (data) ║
║ ║
║ Updated code so that the input string from the command line was a ║
║ list of drives to perform the services on. This change was made ║
║ to allow SYSOP's with multiple download drives to scan all his ║
║ download drives for duplicates. (Here you go Charlie, your name ║
║ in lights.) This version was inspired by Charlie Innusa, a sysop ║
║ running RBBS-PC on only nine 32 Megabyte download drives. You can ║
║ call his BBS, PC-Rockland at 914-353-2157 Subscription node, or ║
║ 914-353-2176 free node ║
║ ║
║ FINDDUPE ABCDEF - find duplicate files across drives A, B, C, ... ║
║ approximate time to handle 10K files = 20 Min ║
║ for reading of directory and sorting. Note, ║
║ sort will need 800K of diskspace for the sort. ║
║ ║
╠══════════════════════════════════════════════════════════════════════╣
║ Version 3.1 made by author ║
║ Fix in the DOS time routine for hours less than 10 A.M. ║
║ Changes made December 29, 1985 ║
╠══════════════════════════════════════════════════════════════════════╣
║ Version 3.2 made by author ║
║ Changes in the way that the output was written to a file when in ║
║ floppy mode. So that the output file goes to a new floppy. ║
╚══════════════════════════════════════════════════════════════════════╝
╔══════════════════════════════════════════════════════════════════════╗
║ Yours for better Computing ║
║ Karson W. Morrison Caleb Computing Center║
╚══════════════════════════════════════════════════════════════════════╝
╔══════════════════════════════════════════════════════════════════════╗
║ ║
║ NOTE: ║
║ ║
║ A command line is used as input if entered else the default drive ║
║ is used. ║
╚══════════════════════════════════════════════════════════════════════╝
}
const
Max_dir = 300; { Max number of directory entries }
{ it can be upped }
{ Changes for 2.04 }
MaxWin = 1; { Max number of windows open at a time }
{ Above Changes for 2.04 }
type
DirRec = { My Sort Record }
record
FileDrive : string[1]; { Drive leter of file} {3.0}
FileNme : string[14]; { File Name }
FileDir : string[36]; { Concatinated Directory Tree }
FileAttributes : string[5]; { Codes for System, hidden, dir etc. }
FileMO : integer; { File creation Month }
FileDA : integer; { File creation Day }
FileYR : integer; { File creation Year }
FileHR : integer; { File creation Hour 24 hour clock }
FileMN : integer; { File creation Minute 60 min clock }
FileSiLow : integer; { Low order byte file size }
FileSiHigh : integer; { High order byte file size }
end;
SortSave = ^Byte;
String20 = string [ 20 ];
RegRec = { The data to pass to DOS }
record
AX, BX, CX, DX, BP, SI, DI, DS, ES, Flags : Integer;
end;
var
FilVar : text; { Is it CON: or LST: }
FilVar1 : text; { Is it CON: or LST: }
DirectryRec : DirRec;
DiskOutput, { Do we want Disk output }
Print, { Do we want paper or screen }
FirstTime, { First time in this routine }
DirCont, { is this dir on the previous page }
NotDir : Boolean; { This is not a directory rec I read }
Regs : RegRec; { Dos Registers }
DTA : array [ 1..43 ] of Byte; { Back from DOS }
Mask : array [ 1..50 ] of Char; { What do we read DOS calls }
NamR : String20; { The file name from the DTA }
SaveFile : SortSave; { Save this type in a getmen instr }
timestr : string[11]; { like it says }
datestr : string[15]; { " }
ErrResult, { Error Switches }
Error,
XDir, YDir, I, Z : Integer; { screen position }
Buffer, { Used in file name manipulation }
Buffer1, { " }
Buffer2 : String [50]; { " }
DirTable : Array [ 1..Max_dir ] of string[50]; { Dirs Found }
E, E_use, { Working integers }
A, B, C, { " }
PageNo : integer; { Page being printed }
PageNoDup : integer; { Page being printed }
OldName : string [14]; { Work areas for duplicate check }
OldDir : string [36]; { Same as DirRec }
OldAttr : string[5]; { " }
OldHi, { " }
OldLo, { " }
OldMO, { " }
OldDA, { " }
OldYR, { " }
OldHR, { " }
OldMN : integer; { " }
OldSI : real; { " }
WrkMN : string[2]; { Work Month }
WorkName : string[14];
{ Change for version 2.04 Following Option was changed to Char }
Option : char; { What option did you want from screen }
Option1 : char; { What option did you want from screen }
Option2 : char; { Is this a Hard Drive or Floppy }
{ Above change made for 2.04 }
ReadDefaultDrive, { Am I reading my default drive }
HardDrive, { Do I have a hard drive or floppies }
MatchFound : Boolean; { Oh! Oh! you have two files the same }
FloppyNumber, { How many floppies have I read }
ScreenLines : integer; { How many lines I've printed }
ScreenLines1 : integer; { How many lines I've printed }
Temp : string[1]; { This is not the Temperature }
SortResult, { Did the sort work }
FileDateDos, { Dos format for date }
FileHourDos, { Dos format for Hour }
FileYear, { File Year actual not just since 1980 }
FileMonth, { File month }
FileDay, { File Day }
FileHour, { File Hour }
FileMinute, { File Minute }
FileWork, { Work area }
FileWork2, { Work area }
FileLow, { Work area }
FileHIgh, { Work area }
NumberRecs : integer; { How many records on disk }
FileWork3 : real; { Work area for file size }
DiskUse : real; { Work area for Disk space in use }
FileUse : integer; { Work area for file space used }
FileUse1K : real; { Work area if 1K blocks }
FileUse2K : real; { Work area if 2K blocks }
FileUse4K : real; { Work area if 4K blocks }
FileUseWork : string[11]; { Work area to print disk use }
Drive_ctr : integer; { Turbo 3.0 Drive letter in use}
CurDrive : String[1]; { Turbo 3.0 Current drive }
DriveString : string[30]; { Drive string command-line }
VolumeIdWrite : string[16]; { VolumeID }
VolumeIdRead : string[16]; { VolumeID }
{ Changes for 2.04 include window }
{$IWindo.INC}
{ Above Change for version 2.04 }
{$ISORT.BOX} { This is from Borland in their Toolbox package }
procedure date; { What is todays date }
const
montharr : array [1..12] of string[3] =
('Jan','Feb','Mar','Apr','May',
'Jun','Jul','Aug','Sep','Oct','Nov','Dec');
var
regs:regrec;
month, day:string[2];
year:string[4];
dx, cx, result, tmpmonth:integer;
begin
with regs do
begin
ax:= $2a shl 8;
end;
msdos (regs);
with regs do
begin
str(cx:4, year);
str(dx shr 8:2, month);
str(dx mod 256:2, day);
end;
if month[1] = ' ' then month[1] := '0';
val (month, tmpmonth, result);
datestr:= day + '-' + montharr[tmpmonth] + '-' + year
end; { procedure date }
{----------------------------------------------------------------------------}
{ This routine gets the DOS time and makes it look good }
{ Note: The Time routine which is used here was picked up on a bulletin
board and it has some bugs in it when the time was around midnight
and around noon. (12 midnight is 12 am and noon is 12 pm) This
routine works to the best of my understanding }
{ Modified in version 2.05 }
procedure time; { What is the current time }
var { Not on your watch! in the computer }
regs:regrec;
ah, al, ch, cl, dh:byte;
hour, min, sec, ampm:string[2];
tmptime, result:integer;
begin
ah := $2c;
with regs do
begin
ax := ah shl 8 + al;
end;
intr($21,regs);
with regs do
begin
str(cx shr 8:2, hour);
str(cx mod 256:2, min);
str(dx shr 8:2, sec);
end;
if (hour > '11') then
ampm := 'pm'
else
ampm := 'am';
if (hour < ' 1') then
begin
ampm := 'am';
hour := '12';
end;
if (hour > '12') then
begin
val (hour, tmptime, result);
tmptime:= tmptime - 12;
str (tmptime:2, hour);
end;
if (min[1] = ' ') then
min[1]:= '0';
if (sec[1] = ' ') then
sec[1]:= '0';
timestr := hour + ':' + min + ':' + sec + ' ' + ampm;
end; { procedure time }
{----------------------------------------------------------------------------}
{ This routine reads the volume id in a directory }
{ Written by Karson Morrison Caleb Computing Center Numbers 13:30 }
procedure ReadVolume(DriveWanted:char);
var i,a : integer;
begin
VolumeIDWrite := DriveWanted + ':\????????.???' + chr(0);
for i := 1 to length(VolumeIDWrite) do
Mask[i] := VolumeIDWrite[i];
VolumeIDRead := ' ';
Regs.AX := $4E00; { Get first directory entry }
Regs.DS := Seg(Mask); { Point to the file Mask }
Regs.DX := Ofs(Mask);
Regs.CX := 8; { Store the option for Volume label }
MSDos(Regs); { Execute MSDos call }
Error := Regs.AX and $FF; { Get Error return }
a := 0;
if error = 0 then
for i := 1 to 12 do
if i <> 9 then
begin
a := a + 1;
VolumeIDRead[a] := Chr(Mem[Seg(DTA):Ofs(DTA)+29+i]);
end;
for i := 1 to 12 do
if VolumeIDRead[i] = Chr(0) then
VolumeIDRead[i] := ' ';
{ new routine in version 3.02 for spaces in middle of vol-id }
i := 11;
repeat
if VolumeIDRead[i] = ' ' then
i := i - 1
else
begin
VolumeIdRead[0] := Chr(i);
i := 1;
end;
until i = 1;
{ end of new routine for version 3.02 }
end;
{----------------------------------------------------------------------------}
{ This routine writes the volume id to a disk }
{ Written by Karson Morrison Caleb Computing Center Numbers 13:30 }
procedure WriteVolume(DriveWanted :char);
var i,a : integer;
begin
VolumeIDWrite := DriveWanted + ':' + VolumeIDWrite + chr(0);
a := 0;
for i := 1 to length(VolumeIDWrite) do
if i <> 11 then
begin
a := a + 1;
Mask[a] := VolumeIDWrite[i];
end
else
begin
a := a + 1;
Mask[a] := '.';
a := a + 1;
Mask[a] := VolumeIDWrite[i];
end;
Regs.AX := $3C00; { Create file }
Regs.DS := Seg(Mask); { Point to the file Mask }
Regs.DX := Ofs(Mask);
Regs.CX := 8; { Store the option for Volume label }
MSDos(Regs); { Execute MSDos call }
Regs.BX := Regs.AX; { Put file handle in BX }
Regs.AX := $3E00; { Close the file }
MSDos(Regs); { Execute MSDos call }
Error := Regs.AX and $FF; { Get Error return }
end;
{----------------------------------------------------------------------------}
procedure SetUpDTA;
begin
Regs.AX := $1A00; { Function used to set the DTA }
Regs.DS := Seg(DTA); { store the parameter segment in DS }
Regs.DX := Ofs(DTA); { " " " offset in DX }
MSDos(Regs); { Set DTA location }
Error := Regs.AX and $FF;
end;
procedure ReadFirst;
begin
Regs.AX := $4E00; { Get first directory entry }
Regs.DS := Seg(Mask); { Point to the file Mask }
Regs.DX := Ofs(Mask);
Regs.CX := 23; { Store the option }
MSDos(Regs); { Execute MSDos call }
Error := Regs.AX and $FF; { Get Error return }
end;
procedure ReadNext;
begin
Error := 0;
Regs.AX := $4F00; { Function used to get the next }
{ directory entry }
Regs.CX := 23; { Set the file option }
MSDos( Regs ); { Call MSDos }
Error := Regs.AX and $FF; { get the Error return }
end;
procedure SetUpNamR; { Get the file name from the directory }
begin
repeat
NamR[I] := Chr(Mem[Seg(DTA):Ofs(DTA)+29+I]);
I := I + 1;
{ Changes for version 2.01 follow this note
Changes made by the author }
until not (NamR[I-1] in [' '..#$7F]) or (I>20); { Note: The second item }
{ being compared as in [' '..#$7F] is }
{ the 7Fh char DEL }
{ Changes for version 2.01 are in front of this note }
NamR[0] := Chr(I-1); { set string length because assigning }
{ by element does not set length }
end;
procedure Set_up_Dir_Chg; { Get a new directory from the table }
var
temp : string[50] ;
temp1 : string[50] ;
begin
E_use := E_Use + 1;
temp := DirTable[E_use];
temp1 := temp;
if temp[2] <> ':' then
temp := CurDrive + ':' + temp;
temp[1] := CurDrive ;
DirTable[E_use] := temp;
Buffer := DirTable[E_use] + '\????????.???' + Chr( 0); {3.0}
Buffer1 := DirTable[E_use];
GoToXY(1,YDir+1);
ClrEol;
Writeln(Buffer1);
XDir := XDir + 1;
if XDir > 75 then begin
XDir := Z;
Z := Z+1;
end;
if Z > 75 then begin
Z := 26;
XDir := 25;
end;
GoToXY(XDir,YDir);
if (Z and 1) = 0 then Write('.') { This puts a . on the screen each }
else Write('*'); { This puts a * on the screen each }
if length(Buffer1) = 1 then Buffer1 := '';
for I := 1 to length(Buffer) do
Mask[I] := Buffer[I];
end;
procedure FindDate; { Translate the Date from the Disk to }
begin { Something readable }
FileMonth := 0; { yyyyyyymmmmddddd in bits}
FileDay := 0;
FileDateDos := MemW[Seg(DTA):Ofs(DTA)+24];
FileYear := FileDateDos shr 9; { drop off the last 9 positions }
FileYear := FileYear + 80; { years are added to base year of 1980 }
FileWork := FileDateDos shl 7; { drop off the first 7 positions }
FileMonth := FileWork shr 12; { now move it back to the right }
FileWork := FileDateDos shl 11; { drop off the left 11 positions }
FileDay := FileWork shr 11; { now move back to the right }
end;
procedure FindTime; { Get the time and put it in a format that }
begin { we can use. The Dos Format in bits is }
FileHour := 0; { hhhhhmmmmmmsssss }
FileMinute := 0;
FileHourDos := MemW[Seg(DTA):Ofs(DTA)+22];
FileHour := FileHourDos shr 11; { Shift it around so the minutes and }
FileWork := FileHourDos shl 5; { seconds disappear }
FileMinute := FileWork shr 10;
end;
procedure FindSize; { Get the file size and format it so we can }
begin { use it }
Filelow := MemW[Seg(DTA):Ofs(DTA)+26]; { Get from DTA, Low byte of size }
FileHigh := MemW[Seg(DTA):Ofs(DTA)+28]; { Get from DTA, High byte }
end;
procedure CalculateSize;
begin
FileWork := DirectryRec.FileSiLow;
FileWork2 := Filework shr 15;
FileWork3 := FileWork2 * 32768.0; { yes! Save the size }
FileWork2 := FileWork shl 1; { Get rid of high bit }
FileWork := FileWork2 shr 1; { Now back to where we were }
FileWork3 := FileWork3 + FileWork; { Lets add them together }
FileWork := DirectryRec.FileSiHigh;
FileWork3 := FileWork3 + (FileWork * 65536.0); { Make size total }
end;
procedure PrintDTA;
var
FileAttr : Byte;
begin
FileAttr := Byte(Mem[Seg(DTA):Ofs(DTA)+21]);
if FileAttr > 31 then { File Not Archived But we won't print this }
begin
FileAttr := FileAttr - 32;
end;
DirectryRec.FileAttributes := ' '; { Make it all spaces }
if FileAttr > 15 then { This is a directory entry }
begin { Let's do it to it }
FileAttr := FileAttr - 16;
E := E + 1;
Buffer2 := Buffer1;
A := Length(Buffer2) + 1;
B := Length(NamR);
C := 1;
Buffer2[A] := '\';
repeat
A := A + 1;
Buffer2[A] := NamR[C];
C := C + 1;
until C > B;
if Buffer2[2]<>':' then
Buffer2 := CurDrive + ':' + Buffer2;
Buffer2[0] := Chr(A - 1);
DirectryRec.FileAttributes[4] := '*'; { Sub Directry }
DirTable[ E ] := Buffer2;
end;
if FileAttr > 7 then
begin
FileAttr := FileAttr - 8
end;
if FileAttr > 3 then
begin
DirectryRec.FileAttributes[3] := 'S'; { System File }
FileAttr := FileAttr - 4;
end;
if FileAttr > 1 then
begin
DirectryRec.FileAttributes[2] := 'H'; { Hidden File }
FileAttr := FileAttr - 2;
end;
if FileAttr > 0 then
begin
DirectryRec.FileAttributes[1] := 'R'; { Read Only }
end;
end;
procedure FormatAndReleaseSort; { Yep that is what it is }
begin
DirectryRec.FileDrive := CurDrive;
DirectryRec.FileNme := ' '; { Blank it out }
DirectryRec.FileNme := NamR; { Get file name }
DirectryRec.FileNme[0] := Chr(13); { Now make it 13 long }
if HardDrive then
DirectryRec.FileDir := Buffer1 { Get Directory its in }
else
DirectryRec.FileDir := CurDrive + ':' + VolumeIdRead +
copy(Buffer1,3,48);
FindDate; { Make date readable }
FindTime; { Time also }
FindSize; { File size }
DirectryRec.FileMO := FileMonth; { Complete setting up }
DirectryRec.FileDA := FileDay; { Sort Record }
DirectryRec.FileYR := FileYear;
DirectryRec.FileHR := FileHour;
DirectryRec.FileMN := FileMinute;
DirectryRec.FileSiLow := FileLow;
DirectryRec.FileSiHigh := FileHigh;
SortRelease(DirectryRec); { Let'er go! }
End;
function GetDrive : char;
var
al : byte;
dr : char absolute al;
begin
Regs.AX := $19 shl 8; { Get current drive letter in AL }
MsDos(Regs);
GetDrive := Chr(lo(Regs.AX) + $41);
end;
procedure Inp; { ReadDirs this procedure is forward declared in SORT.BOX }
begin { This reads the directories and releases }
{ to the sort }
ReadDefaultDrive := False; { Am I reading the default drive }
if ParamCount<>0 then DriveString:=Paramstr(1)
else
begin
DriveString := GetDrive;
end;
repeat
NotDir := True;
E := 0; E_Use := 0;
{ new routine in version 3.02 to check if default drive is an input drive }
{ if yes then you must put a new floppy in for the output (if on file) }
for drive_ctr:=1 to length(DriveString) do
begin
if Upcase(DriveString[drive_ctr]) = GetDrive then
ReadDefaultDrive := True; { yes I'm reading the default drive }
if DriveString[drive_ctr] in ['A'..'Z','a'..'z']
then { if it is not alpha then delete (probably ':') }
else
delete(DriveString,drive_ctr,1);
end;
{ end of new routine for version 3.02 }
for drive_ctr:=1 to length(DriveString) do
begin
E := succ(E);
CurDrive:=UpCase(DriveString[drive_ctr]);
Buffer := CurDrive + ':';
NotDir := True;
Buffer1 := ''; Buffer2 := Buffer; DirTable[E] := Buffer;
Buffer[ length(Buffer) + 1 ] := Chr(0);
Buffer[0] := chr(length(buffer));
FillChar(DTA,SizeOf(DTA),0); { Initialize the DTA buffer }
FillChar(Mask,SizeOf(Mask),0); { Initialize the mask }
FillChar(NamR,SizeOf(NamR),0); { Initialize the file name }
SetUpDTA;
Error := 0;
if not HardDrive then
begin
VolumeIdRead := '';
FloppyNumber := FloppyNumber + 1;
ReadVolume(CurDrive);
if error <> 0 then
begin
GoToXY(1,20);
Write('Volume-ID not present. Drive ',CurDrive,': ');
Write('What ID do you want -----------');
GoToXY(1,21);
Write('Press return if Volume-ID not wanted!');
GoToXY(55,20);
Readln(VolumeIDWrite);
GoToXY(1,21); ClrEol; GoToXY(1,20); ClrEol;
if length(VolumeIDWrite) <> 0 then
begin
for i := 1 to length(VolumeIDWrite) do
VolumeIDWrite[i] := Upcase(VolumeIDWrite[i]);
VolumeIDRead := VolumeIdWrite;
WriteVolume(CurDrive);
end
else
begin
Str(FloppyNumber:3,VolumeIDRead);
VolumeIDRead := 'Floppy' + VolumeIDRead;
end;
end;
end;
While E_Use < E do
begin
Set_Up_Dir_Chg;
ReadFirst; { This does the first read for a directory }
if (Error = 0) then
begin
I := 1;
SetUpNamR;
if NamR[1] = '.' then NotDir := False;
if NotDir and (Error = 0) then
begin
PrintDTA; { This gets the file attributes }
FormatAndReleaseSort; { Build the record }
end;
end;
while (Error = 0) do begin
NotDir := True;
ReadNext; { This reads other entries in directory but }
if (Error = 0) then { the first }
begin
I := 1;
SetUpNamR;
if NamR[1] = '.' then NotDir := False; { Is it a dot directory }
if NotDir and (Error = 0) then { No it is not }
begin
PrintDTA;
FormatAndReleaseSort;
end;
end;
end;
end;
end;
if not HardDrive then
begin { Only ask the following question if floppies }
GoToXY(1,18); ClrEol;
Write('Press Return when next floppy ready. (Enter (*) when done!)');
Read(Kbd,Option1);
if Option1 <> '*' then
begin
GoToXY(1,18); ClrEol;
Write('Reading the Directories');
end;
end
else
Option1 := '*'; { This is a hard disk therefore only read once }
until Option1 = '*';
Writeln; { All done reading the directories }
Write('Sorting the Directory Data');
ClrEol;
end; { End of procedure Inp }
function Less; { this boolean function has two parameters, X and Y }
{ and is forward declared in SORT.BOX }
var
FirstDir : DirRec absolute X;
SecondDir : DirRec absolute Y;
begin
if option = '4' then { Tree Directory option }
begin
Less := (FirstDir.FileDrive < SecondDir.FileDrive)
or
((FirstDir.FileDrive = SecondDir.FileDrive) and
(FirstDir.FileDir < SecondDir.FileDir))
or
((FirstDir.FileDrive = SecondDir.FileDrive) and
(FirstDir.FileDir = SecondDir.FileDir) and
(FirstDir.FileAttributes[4] < SecondDir.FileAttributes[4]))
{ FileAttr[4] is the sub dir code pos }
or
((FirstDir.FileDrive = SecondDir.FileDrive) and
(FirstDir.FileDir = SecondDir.FileDir) and
(FirstDir.FileAttributes[4] = SecondDir.FileAttributes[4]) and
(FirstDir.FileNme < SecondDir.FileNme));
end
else { Sorted file option }
begin { this tells the sort which of the }
Less := (FirstDir.FileNme < SecondDir.FileNme) { two entries are }
or
((FirstDir.FileNme = SecondDir.FileNme) and { first and which }
(FirstDir.FileDir < SecondDir.FileDir)); { is second }
end;
end;
procedure SetUpOldArea; { We need to keep the old }
begin { Stuff around to see if }
OldName := DirectryRec.FileNme; { Matches the new stuff }
OldDir := DirectryRec.FileDir; { This is used for the duplicate }
OldAttr := DirectryRec.FileAttributes; { compares }
OldDA := DirectryRec.FileDA;
OldMO := DirectryRec.FileMO;
OldYR := DirectryRec.FileYR;
OldHR := DirectryRec.FileHR;
OldMN := DirectryRec.FileMN;
CalculateSize;
OldSI := FileWork3;
end;
procedure FixMinute; { Make the time readable }
begin { put a 0 in front of one }
if length(WrkMN) = 1 then { character minutes }
begin
WrkMN := '0' + WrkMn;
end;
end;
procedure HeadingDupe; { Headings for the reports }
begin
PageNoDup := PageNoDup + 1;
Writeln(FilVar,'');
Write(FilVar,' Directory list for duplicate files. ',Datestr,' ',Timestr);
Writeln(FilVar,' Page ',PageNoDup);
Writeln(FilVar,' * = Sub Dir: R = Read only; H = Hidden: S = System');
Writeln(FilVar,' Files Date Time Size Directory ');
WriteLn(FilVar,'');
end;
procedure HeadingAll; { Heading for the reports }
begin
PageNo := PageNo + 1;
Writeln(FilVar1,'');
Write(FilVar1,' Directory list for all files. ',Datestr,' ',Timestr);
Writeln(FilVar1,' Page ',PageNo);
Writeln(FilVar1,' * = Sub Dir: R = Read only: H = Hidden: S = System');
Writeln(FilVar1,' Files Date Time Size Directory ');
WriteLn(FilVar1,'');
end;
procedure HeadingTree; { Heading for the Tree reports }
begin
PageNo := PageNo + 1;
Writeln(FilVar,'');
Write(FilVar,' Tree Directory list for all files. ',Datestr,' ',Timestr);
Writeln(FilVar,' Page ',PageNo);
Writeln(FilVar,' * = Sub Dir: R = Read only: H = Hidden: S = System');
Writeln(FilVar,' Files Date Time Size');
end;
Procedure SetUpOutputFile; { This routine created in version 3.02 }
begin { it was in the main section until now }
{ following instruction added in version 3.02 }
FreeMem(SaveFile,6000);
{ above instruction added in 3.02 }
MkWin(20,7,60,13,2,14,1);
Print := False;
DiskOutput := False;
if Option = '3' then
begin
Print := True;
DiskOutput := True;
Assign(FilVar,'DUPLICAT.DTA');
Assign(FilVar1,'DIRECTRY.DTA');
{ new routine for version 3.02 }
if ReadDefaultDrive and not HardDrive then
begin
Writeln('Place empty floppy in Drive ',GetDrive,':');
Write('Press any key to continue');
repeat until keypressed;
end;
{ end of new routine }
Writeln;
Writeln('Duplicate output on DUPLICAT.DTA');
Writeln('Directory output on DIRECTRY.DTA');
Rewrite(FilVar);
Rewrite(FilVar1);
TimeDelay(5); { Wait 5 seconds }
RmWin;
end
else
begin
Writeln(' For Output on printer:------------(P)');
Writeln(' For Output in file DIRECTRY.DTA:--(F)');
Writeln(' For Output on screen:-------------(S)');
Writeln;
repeat
GoToXY(5,5);
Write('Option:');
read(Kbd,Option1);
Writeln(Upcase(Option1));
until Upcase(Option1) in ['P','F','S'];
RmWin;
if Upcase(Option1) = 'P' then
begin { Set up printer for listing }
Print := True;
if Option in ['1','4'] then
begin
Assign(FilVar,'LST:');
Rewrite(FilVar);
end
else
begin
Assign(FilVar1,'LST:');
Rewrite(Filvar1);
end;
end;
if Upcase(Option1) = 'F' then
begin { Set up file for listing }
Print := True;
DiskOutput := True;
if Option in ['1','4'] then
begin
{ new routine for version 3.02 }
MkWin(20,7,60,13,2,14,1);
if ReadDefaultDrive and not HardDrive then
begin
Writeln('Place empty floppy in Drive ',GetDrive,':');
Write('Press any key to continue');
repeat until keypressed;
end;
{ end of new routine }
Assign(FilVar,'DIRECTRY.DTA');
Rewrite(FilVar);
RmWin;
end
else
begin
{ new routine for version 3.02 }
MkWin(20,7,60,13,2,14,1);
if ReadDefaultDrive and not HardDrive then
begin
Writeln('Place empty floppy in Drive ',GetDrive,':');
Write('Press any key to continue');
repeat until keypressed;
end;
{ end of new routine }
Assign(FilVar1,'DIRECTRY.DTA');
Rewrite(Filvar1);
RmWin;
end;
end;
if Upcase(Option1) = 'S' then
begin { Set up file for listing }
if Option in ['1','4'] then
begin
Assign(FilVar,'CON:');
Rewrite(FilVar);
end
else
begin
Assign(FilVar1,'CON:');
Rewrite(Filvar1);
end;
end;
end;
end;
procedure OutP; { this procedure is forward declared in SORT.BOX }
begin { This takes the sorted data and creates }
{ CLRSCR instruction moved later in version 3.00 }
{ the following is a new instruction for version 3.02 }
SetUpOutputFile; { Prepare for output file }
OldName := ' '; { Clear out the field }
NumberRecs := 0;
OldDir := ' ';
DirCont := False;
Buffer[3] := chr(0); { Shorten the drive identifier here }
Buffer[0] := chr(2);
if print then
begin
{ following instruction added in version 3.00 }
GoToXY(1,19); ClrEol;
GoToXY(1,18); ClrEol;
GoToXY(1,17); ClrEol;
{ above instruction added in version 3.00 }
if DiskOutput then
begin
Write(' Creating the file DIRECTRY.DTA');
end
else
begin
Write(' Printing the Report '); { Screen }
end;
end
{ following instructions were added or moved in version 3.00 }
else
begin
ClrScr; { the required reports (Screen or Paper) }
end;
{ above instructions were added or moved in version 3.00 }
if Option in ['1','3'] then
HeadingDupe; { Do you want the Duplicate }
if Option in ['2','3'] then
HeadingAll; { Do you want all the Directories }
if Option = '4' then
HeadingTree; { Do you want the Tree Dir }
repeat
SortReturn(DirectryRec); { Hay it's back, just like magic }
NumberRecs := NumberRecs + 1;
CalculateSize;
DiskUse := DiskUse + FileWork3;
FileUse := DirectryRec.FileSiLow; { Lets play with the bits }
FileWork := FileUse and 1023; { Turn off all bits but less than 1K }
FileWork2 := FileUse shr 10; { Shift the 1K multiple into place }
if FileWork <> 0 then { If not exact 1K alignment }
FileUse1K := FileUse1k + FileWork2 + 1 { Then add 1 and save }
else { If exact 1K alignment }
FileUse1K := FileUse1K + FileWork2; { Just keep the multiple }
FileWork := FileUse and 2047; { Turn off all bits but less than 2K }
FileWork2 := FileUse shr 11; { Shift the 2K multiple into place }
if FileWork <> 0 then { If not exact 2K alignment }
FileUse2K := FileUse2k + FileWork2 + 1 { Then add 1 and save }
else { If exact 2K alignment }
FileUse2K := FileUse2K + FileWork2; { Just keep the multiple }
FileWork := FileUse and 4095; { Turn off all bits but less then 4K }
FileWork2 := FileUse shr 12; { Shift the 4K multiple into place }
if FileWork <> 0 then { If not exact 4K alignment }
FileUse4K := FileUse4K + FileWork2 + 1 { Then add 1 and save }
else { If exact 4K alignment }
FileUse4K := FileUse4K + FileWork2; { Just keep the multiple }
FileUse := DirectryRec.FileSiHigh; { Now get the high byte }
FileUse1K := FileUse1K + (FileUse * 64); { Save the 1K multiple }
FileUse2K := FileUse2K + (FileUse * 32); { Save the 2K multiple }
FileUse4K := FileUse4K + (FileUse * 16); { Save the 4K multiple }
if Option in ['1','3'] then { You want the Duplicate entries }
begin
WorkName := DirectryRec.FileNme;
if OldName < WorkName then { its not duplicate }
begin
SetUpOldArea;
if MatchFound then
begin
MatchFound := False;
Writeln(FilVar,'');
ScreenLines := ScreenLines + 1;
end;
end
else { Yes it is }
begin
if not MatchFound then
begin
if ((print) and (ScreenLines > 50)) { 50 on paper is ok }
or ((not print) and (ScreenLines > 17)) then
begin { 17 is about all you want }
if print then { on the screen at a time }
begin
Writeln(FilVar,#$0C);
end
else
begin
Write(' More');
repeat until keypressed;
{ I'll wait until you read these }
ClrScr; { Lets start anew }
end;
HeadingDupe; { Put the heading back }
ScreenLines := 0; { I got nothing on the screen }
end;
Write(FilVar,OldAttr); { Write the old data }
Write(FilVar,OldName,' ');
Write(FilVar,OldMO:2,'/',OldDA:2,'/',OldYR);
Str(OldMN,WrkMN); { Convert numeric to string }
FixMinute; { now make it more readable }
Write(FilVar,' ', OldHR:2,':',WrkMN);
Write(FilVar,' '); { Continue printing }
Write(FilVar,OldSI:9:0); { Print Size }
Write(FilVar,' '); { Continue printing }
if length(OldDir) > 0 then { Is it the main directory }
Writeln(FilVar,OldDir) { Nope }
else
Writeln(FilVar,'\'); { this is the main directory }
ScreenLines := ScreenLines + 1; { Its one more than it was }
end;
Write(FilVar,DirectryRec.FileAttributes); { Lets write the current }
Write(FilVar,DirectryRec.FileNme,' '); { Record }
Write(FilVar,DirectryRec.FileMO:2,'/');
Write(FilVar,DirectryRec.FileDA:2,'/');
Write(FilVar,DirectryRec.FileYR);
Str(DirectryRec.FileMN, WrkMN);
FixMinute;
Write(FilVar,' ',DirectryRec.FileHR:2,':',WrkMN);
Write(FilVar,' ');
Write(FilVar,FileWork3:9:0);
Write(FilVar,' ');
if length(DirectryRec.FileDir) > 1 then
Writeln(FilVar,DirectryRec.FileDir)
else
Writeln(FilVar,'\'); { this is the main directory }
ScreenLines := ScreenLines + 1;
SetUpOldArea;
MatchFound := True;
end;
end;
if Option in ['2','3'] then { You want them all }
begin
if ((print) and (ScreenLines1 > 50))
or ((not print) and (ScreenLines1 > 18)) then
begin
if print then
begin
Writeln(FilVar1,#$0C);
end
else
begin
Write(' More');
repeat until keypressed;
ClrScr;
end;
HeadingAll;
ScreenLines1 := 0;
end;
Write(FilVar1,DirectryRec.FileAttributes);
Write(FilVar1,DirectryRec.FileNme,' '); { Let's show'em what we found }
Write(FilVar1,DirectryRec.FileMO:2,'/');
Write(FilVar1,DirectryRec.FileDA:2,'/');
Write(FilVar1,DirectryRec.FileYR);
Str(DirectryRec.FileMN, WrkMN);
FixMinute;
Write(FilVar1,' ',DirectryRec.FileHR:2,':',WrkMN);
Write(FilVar1,' ');
Write(FilVar1,FileWork3:9:0);
Write(FilVar1,' ');
if length(DirectryRec.FileDir) > 1 then
Writeln(FilVar1,DirectryRec.FileDir)
else
Writeln(FilVar1,'\');
ScreenLines1 := ScreenLines1 + 1;
end;
if Option = '4' then
begin
if ((print) and (ScreenLines > 50))
or ((not print) and (ScreenLines > 18))
or ((not print) and (ScreenLines > 15)
and (OldDir <> DirectryRec.FileDir)) then
begin
if print then
begin
Writeln(FilVar,#$0C);
end
else
begin
Write(' More');
repeat until keypressed;
ClrScr;
end;
HeadingTree;
ScreenLines := 0;
if OldDir = DirectryRec.FileDir then
begin
DirCont := True;
OldDir := ' ';
end;
end;
if OldDir <> DirectryRec.FileDir then { print the dir were in }
begin
Writeln(FilVar,'');
Write(FilVar,' Directory ');
begin
if length(DirectryRec.FileDir) > 1 then
Write(FilVar,DirectryRec.FileDir)
else
Write(FilVar,'\');
end;
if DirCont then
begin
DirCont := False;
Writeln(FilVar,' (cont.)');
end
else
Writeln(FilVar,'');
OldDir := DirectryRec.FileDir;
Writeln(FilVar,'');
ScreenLines := ScreenLines + 3;
end;
Write(FilVar,DirectryRec.FileAttributes);
Write(FilVar,DirectryRec.FileNme,' '); { Let's show'em what we found }
Write(FilVar,DirectryRec.FileMO:2,'/');
Write(FilVar,DirectryRec.FileDA:2,'/');
Write(FilVar,DirectryRec.FileYR);
Str(DirectryRec.FileMN, WrkMN);
FixMinute;
Write(FilVar,' ',DirectryRec.FileHR:2,':',WrkMN);
Write(FilVar,' ');
Writeln(FilVar,FileWork3:9:0);
ScreenLines := ScreenLines + 1;
end;
until SortEOS; { Do it until its done }
end;
begin { Main program }
ClrScr;
Buffer := '';
DiskUse := 0; { Zero out field }
FileUse := 0;
FileUse1K := 0;
FileUse2K := 0;
FileUse4K := 0;
FloppyNumber := 0;
Time; { Get the time }
Date; { Get the date }
{ new instruction for version 3.02 }
GetMem(SaveFile,6000); { Save 6000 bytes from the sort }
{ for use when a file is opened }
FirstTime := True; { First time here }
MatchFound := False; { Haven't found any matches yet }
GoToXY(10,1); { Fill the screen with data }
Write('Directory List Program Version 3.02'); { This is it }
GoToXY(10,3);
Write('Written and Copyright (C) by');
GoToXY(18,6);
Write('Karson W. Morrison'); { This is who did it }
GoToXY(38,7);
Write('Caleb Computing Company Numbers 13:30');
GoToXY(38,8);
Write('Rd 1, Box 531, Ringoes New Jersey, 08551');
GoToXY(18,9);
Write('January 15, 1986'); { And When }
GoToXY(10,11);
Write('OPTIONS:');
GoToXY(11,12);
Write('List only Duplicate files on the disk : (1)');
GoToXY(11,13);
Write('List the entire Directory of the disk : (2)');
GoToXY(11,14);
Write('List both Directry and Duplicate files: (3)');
GoToXY(11,15);
Write('List a Sorted Tree Dir of the disk : (4)');
GoToXY(43,22);
Write('Partial Mods. for Multiple Hard Disks');
GoToXY(58,23);
Write('Ray Bobak - 10/27/1985');
repeat
GoToXY(14,17);
Write('Option: ');
read(Kbd,Option);
GoToXY(22,17);
Writeln(Option);
until Option in ['1'..'4'];
MkWin(20,7,60,13,2,14,1);
Writeln('Are you running this program against');
Writeln('Floppies or a Hard Disk? (F or H)');
Writeln;
Write('Option: ');
Repeat
Read(kbd,Option2);
until (Upcase(Option2)) in ['F','H'];
if Upcase(Option2) = 'H' then
HardDrive := true
else
HardDrive := false;
RmWin;
Writeln;
ScreenLines := 0;
ScreenLines1 := 0;
PageNo := 0;
PageNoDup := 0;
GoToXY(1,18);
XDir := 25; YDir := 18; Z := 26;
Writeln('Reading the Directories');
Write('\');
SortResult := TurboSort(SizeOf(DirectryRec)); { this does the call to the sort }
if SortResult > 1 then { if the sort don't work }
begin { This maybe what is wrong }
if SortResult = 3 then Writeln('Not enouth memory for sorting');
if SortResult = 9 then Writeln('More than 32767 records being sorted');
if sortresult = 10 then Writeln('Disk error during sorting (bad or full)');
if SortResult = 11 then Writeln('Read error during sort (Probably bad disk)');
if sortResult = 12 then Writeln('File creation error (directory may be full)');
end;
Writeln;
if print then
begin
if Option in ['1','3','4'] then
begin
Writeln(FilVar,'');
Write(FilVar,' Number of Directories: ',E-1);
Writeln(FilVar,' Number of Files: ',NumberRecs-E+1);
Writeln(FilVar,' Disk Space used ',DiskUse:11:0);
Writeln(FilVar,' Disk Space used 4K blocks ',(FileUse4K * 4096.0):11:0);
Writeln(FilVar,' Disk Space used 2K blocks ',(FileUse2K * 2048.0):11:0);
Writeln(FilVar,' Disk Space used 1K blocks ',(FileUse1K * 1024.0):11:0);
If not DiskOutput then
Writeln(FilVar,#$0C);
end;
if Option in ['2','3'] then
begin
Writeln(FilVar1,'');
Write(FilVar1,' Number of Directories: ',E-1);
Writeln(FilVar1,' Number of Files: ',NumberRecs-E+1);
Writeln(FilVar1,' Disk Space used ',DiskUse:11:0);
Writeln(FilVar1,' Disk Space used 4K blocks ',(FileUse4K * 4096.0):11:0);
Writeln(FilVar1,' Disk Space used 2K blocks ',(FileUse2K * 2048.0):11:0);
Writeln(FilVar1,' Disk Space used 1K blocks ',(FileUse1K * 1024.0):11:0);
If not DiskOutput then
Writeln(FilVar1,#$0C);
end;
{ the following line was changed in version 3.00 }
GoToXY(1,19); { this is for the Writeln below this }
end;
If DiskOutput then
begin
if Option in ['1','3','4'] then
close(FilVar);
if Option in ['2','3'] then
close(Filvar1);
end;
Write(' Number of Directories: ',E-1);
Write(' Number of Files: ',NumberRecs-E+1);
ClrEol;
Writeln;
Writeln(' Disk Space used ',DiskUse:11:0);
Writeln(' Disk Space used 4K blocks ',(FileUse4K * 4096.0):11:0);
Writeln(' Disk Space used 2K blocks ',(FileUse2K * 2048.0):11:0);
Writeln(' Disk Space used 1K blocks ',(FileUse1K * 1024.0):11:0);
end.